package com.liik.game.mvc.tiled;

import com.liik.game.mvc.GameController;
import com.liik.game.mvc.GameModel;
import com.liik.game.mvc.object.Display;
import com.liik.game.mvc.object.Navigation;
import com.liik.game.mvc.tiled.object.Entity;
import com.liik.game.mvc.tiled.object.MovableEntity;
import com.liik.game.util.Vector;

public abstract class TiledGameController extends GameController {

	protected boolean isPaused = false;

	@Override
	public final void update(GameModel model, Navigation navigation, Display display) {
		TiledGameModel gameModel = (TiledGameModel) model;
		long currentTimeMillis = System.currentTimeMillis();
		if (!isPaused) {
			gameModel.resetEnvironment(); // reset environment
			moveHero(gameModel, navigation); // move hero
			updateEntities(gameModel, currentTimeMillis); // update all entities
			updateHero(gameModel, currentTimeMillis); // update the hero
			collisionHandling(gameModel, currentTimeMillis); // collision
																// handling and
																// environment
																// handling
		}
	}

	private void moveHero(TiledGameModel gameModel, Navigation navigation) {
		if (navigation.pressed) {
			gameModel.getHero().move(gameModel, navigation.target);
		}
	}

	private void updateEntities(TiledGameModel gameModel, long currentTimeMillis) {
		Entity[] entities = gameModel.getAllEntities();
		for (int i = 0; i < entities.length; ++i) {
			Entity entity = entities[i];
			if (entity != null && entity.isActive()) {
				entity.update(gameModel, currentTimeMillis);
			}
		}
	}

	private void updateHero(TiledGameModel gameModel, long currentTimeMillis) {
		gameModel.getHero().update(gameModel, currentTimeMillis);
	}

	private void collisionHandling(TiledGameModel gameModel, long currentTimeMillis) {
		MovableEntity hero = gameModel.getHero();
		Entity[] entities = gameModel.getAllEntities();

		// Collision handling
		for (int i = 0; i < entities.length; ++i) {
			if (isCollision(hero, entities[i])) {
				if (hero.collisionHandlerPriority < entities[i].collisionHandlerPriority)
					entities[i].handleCollision(hero, gameModel, currentTimeMillis);
				else {
					hero.handleCollision(entities[i], gameModel, currentTimeMillis);
				}
			}
		}
		for (int i = 0; i < entities.length; ++i) {
			for (int j = i + 1; j < entities.length; ++j) {
				if (isCollision(entities[i], entities[j])) {
					if (entities[i].collisionHandlerPriority < entities[j].collisionHandlerPriority)
						entities[j].handleCollision(entities[i], gameModel, currentTimeMillis);
					else {
						entities[i].handleCollision(entities[j], gameModel, currentTimeMillis);
					}
				}
			}
		}
		
		// Environment handling
		hero.handleEnvironment(gameModel.getEnvironment(hero.x, hero.y), gameModel, currentTimeMillis);		
		for (int i = 0; i < entities.length; ++i) {
			if (entities[i].isActive()) {
				entities[i].handleEnvironment(gameModel.getEnvironment(entities[i].x, entities[i].y), gameModel, currentTimeMillis);
			}
		}
	}

	private Vector collisionHelper = new Vector();

	private boolean isCollision(Entity entity1, Entity entity2) {
		if (entity1 == null || !entity1.isActive() || entity2 == null || !entity2.isActive()) {
			return false;
		}
		collisionHelper.setDirection(entity1, entity2);
		return collisionHelper.length() < entity1.boundingRadius + entity2.boundingRadius;
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStop() {
		// TODO Auto-generated method stub

	}
}
